/**
  ******************************************************************************
  * @file    Libraries/Device/TS32Fx/TS32Fx_LL_Driver/src/ts32fx_ll_timer.c
  * @author  TOPSYS Application Team
  * @version V1.0.0
  * @date    02-11-2018
  * @brief   This file contains all the TIMER LL firmware functions.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2018 TOPSYS</center></h2>
  *
  *
  ******************************************************************************
  */ 

/* Includes ------------------------------------------------------------------*/
#include "include.h"

/** @addtogroup TS32Fx_StdPeriph_Driver TS32Fx Driver
  * @{
  */
  
/** @defgroup timer_interface_gr TIMER Driver
  * @ingroup  TS32Fx_StdPeriph_Driver
  * @{
  */

/** @addtogroup TIMER_LL_Driver TIMER LL Driver
  * @ingroup  timer_interface_gr
  * @{
  */
  
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

  
/** @defgroup TIMER_LL_Interrupt TIMER LL Interrupt Handle function
  * @ingroup  TIMER_LL_Driver
  * @brief   TIMER LL Interrupt Handle function
  * @{
  */
/* timer count ---------------------------------------------------------------*/

/**
  * @}
  */

/** @defgroup TIMER_LL_Inti_Cfg TIMER LL Initialization And Configuration
  * @ingroup  TIMER_LL_Driver
  * @brief    TIMER LL Initialization And Configuration
  * @{
  */
  

/**
  * @brief  Low layer timer init function
  * @param  p_timer: Set to division and source colock of TIMERx
  * @param  p_init : Configure the p_timer initialization structure
  * @retval None
  */
void ll_timer_init(TIMER_TypeDef *p_timer, TYPE_LL_TIMER_INIT *p_init)
{
    u32 tmr_con;
    //p_timer->TMR_PWM = 0x0000;
    
    tmr_con = p_timer->TMR_CON;
    tmr_con = (tmr_con & (~LL_TIMER_CON_DIVISION_SET(ALL_WORD_FF))) | LL_TIMER_CON_DIVISION_SET(p_init->prescaler);
    tmr_con = (tmr_con & (~LL_TIMER_CON_SRC_SEL(ALL_WORD_FF))) | LL_TIMER_CON_SRC_SEL(p_init->timer_src_sel);
    tmr_con |= LL_TIMER_CON_CNT_PENDING | LL_TIMER_CON_CAP_PENDING;
    p_timer->TMR_CON = tmr_con;
}

/**
  * @brief  Low layer timer delete init function
  * @param  p_timer: Structure pointer set to TIMER or TIMER1
  * @retval None
  */
void ll_timer_deinit(TIMER_TypeDef *p_timer)
{
    TX_ASSERT((TIMER0 == p_timer) || (TIMER1 == p_timer) || (TIMER2 == p_timer) || (TIMER3 == p_timer) || (TIMER4 == p_timer));
}

/**
  * @}
  */

/** @defgroup TIMER_LL_Data_Transfers TIMER LL Data transfers functions
  * @ingroup  TIMER_LL_Driver
  * @brief    TIMER LL Data transfers functions 
  * @{
  */

/**
  * @brief  Low layer timer disable function
  * @param  p_timer  : Structure pointer set to TIMER0~TIMER4
  * @retval None
  */
void ll_timer_stop(TIMER_TypeDef *p_timer)
{
    u32 cnt_con = p_timer->TMR_CON;
    cnt_con = (cnt_con & (~LL_TIMER_CON_MODE_SET(ALL_WORD_FF))) | LL_TIMER_CON_MODE_SET(LL_TIMER_MODE_SEL_DISABLE);
    cnt_con |= LL_TIMER_CON_CNT_PENDING | LL_TIMER_CON_CAP_PENDING;
    p_timer->TMR_CON = cnt_con;
}

/**
  * @brief  Low layer timer start function
  * @param  p_timer  : Structure pointer set to TIMER0~TIMER4
  * @retval None
  */
void ll_timer_start(TIMER_TypeDef *p_timer, TYPE_ENUM_LL_TIMER_MODE_SEL mode_sel)
{
    u32 cnt_con = p_timer->TMR_CON;
    cnt_con = (cnt_con & (~LL_TIMER_CON_MODE_SET(ALL_WORD_FF))) | LL_TIMER_CON_MODE_SET(mode_sel);
    cnt_con |= LL_TIMER_CON_CNT_PENDING | LL_TIMER_CON_CAP_PENDING;
    p_timer->TMR_CON = cnt_con;
}

/**
  * @brief  Low layer timer0~timer4 cnt set
  * @param  p_timer  : Structure pointer set to TIMERx
  * @param  cnt_set  : timer0~timer4 cnt value(timer0~timer3 16bits cnt value, timer4 32bits cnt value)
  * @retval None
  */
void ll_timer_cnt_set(TIMER_TypeDef *p_timer, u32 cnt_set)
{
    if((TIMER0 == p_timer) || (TIMER1 == p_timer) || (TIMER2 == p_timer) || (TIMER3 == p_timer))
    {
        p_timer->TMR_CNT = (u16)cnt_set;
    }
    else if(TIMER4 == p_timer)
    {
        p_timer->TMR_CNT = cnt_set;
    }
}

/**
  * @brief  Low layer timer cnt get
  * @param  p_timer  : Structure pointer set to TIMERx
  * @retval timer cnt value(timer0~timer3 16bits cnt value, timer4 32bits cnt value)
  */
u32 ll_timer_cnt_get(TIMER_TypeDef *p_timer)
{

    return (p_timer->TMR_CNT);

}

/**
  * @brief  set timer to count mode
  * @param  p_timer  : Structure pointer set to TIMERx
  * @param  cnt_cfg  : Structure pointer set to TIMERx counter mode
  * @retval None
  */
void ll_timer_cnt_mode_config(TIMER_TypeDef *p_timer, TYPE_LL_TIMER_CNT_CFG *cnt_cfg)
{
    u32 cnt_con = 0;
    
    p_timer->TMR_CNT  = cnt_cfg->count_initial;
    p_timer->TMR_PR   = cnt_cfg->count_period;
    
    cnt_con = p_timer->TMR_CON;
    /*  cnt_con = (cnt_con & (~LL_TIMER_CON_MODE_SET(ALL_WORD_FF))) | LL_TIMER_CON_MODE_SET(LL_TIMER_MODE_SEL_COUNTER);  */
    if(cnt_cfg->count_ie)
    {
        cnt_con |= LL_TIMER_CON_CNT_IE;
    }
    else
    {
        cnt_con &= ~LL_TIMER_CON_CNT_IE;
    }
    cnt_con &= ~(LL_TIMER_CON_CNT_PENDING | LL_TIMER_CON_CAP_PENDING);
    p_timer->TMR_CON |= cnt_con;
}

/**
  * @brief  set timer to pwm mode
  * @param  p_timer  : Structure pointer set to TIMERx
  * @param  pwm_cfg  : Structure pointer set to TIMERx pwm mode
  * @retval None
  */
void ll_timer_pwm_mode_config(TIMER_TypeDef *p_timer, TYPE_LL_TIMER_PWM_CFG *pwm_cfg)
{
    p_timer->TMR_CNT  = 0;
    p_timer->TMR_PR   = pwm_cfg->pwm_period;
    p_timer->TMR_PWM  = pwm_cfg->pwm_duty;
    #if 0
    p_timer->TMR_CON = ((p_timer->TMR_CON) & (~LL_TIMER_CON_MODE_SET(ALL_WORD_FF))) | LL_TIMER_CON_MODE_SET(LL_TIMER_MODE_SEL_PWM);
    /*  p_timer->TMR_CON |= LL_TIMER_CON_MODE_SET(LL_TIMER_MODE_SEL_PWM);  */
    #endif
}

/**
  * @brief  set timer to capture mode 
  * @param  p_timer  : Structure pointer set to TIMERx
  * @param  cap_cfg  : Structure pointer set to TIMERx capture mode
  * @retval None
  */
void ll_timer_cap_mode_config(TIMER_TypeDef *p_timer, TYPE_LL_TIMER_CAP_CFG *cap_cfg)
{
    u32 cap_con = 0;
    p_timer->TMR_CNT  = 0;
    p_timer->TMR_PR   = 0xFFFFFFFF;
    
    cap_con = p_timer->TMR_CON;
    cap_con = (cap_con & (~LL_TIMER_CON_CAP_EDGE_SET(ALL_WORD_FF))) | LL_TIMER_CON_CAP_EDGE_SET(cap_cfg->capture_edge_sel);
    /*  cap_con = (cap_con & (~LL_TIMER_CON_MODE_SET(ALL_WORD_FF))) | LL_TIMER_CON_MODE_SET(LL_TIMER_MODE_SEL_CAPTURE);  */
    if(cap_cfg->capture_ie)
    {
        cap_con |= LL_TIMER_CON_CAP_IE;
    }
    else
    {
        cap_con &= ~LL_TIMER_CON_CAP_IE;
    }
    cap_con &= ~(LL_TIMER_CON_CNT_PENDING | LL_TIMER_CON_CAP_PENDING);
    p_timer->TMR_CON = cap_con;
}

/**
  * @brief  Infrared timer initialization 
  * @param  p_timer  : Structure pointer set to TIMER5
  * @param  p_init : Configure the p_timer initialization structure
  * @retval None
  */
void ll_irtimer_init(TIMER5_TypeDef *p_timer, TYPE_LL_TIMER_INIT *p_init)
{
    u32 tmr_con;
    p_timer->TMR_PWM = 0x0000;
    p_timer->TMR_IRSTA = 0x0000;
    
    tmr_con = p_timer->TMR_CON;
    tmr_con = (tmr_con & (~LL_TIMER_CON_DIVISION_SET(ALL_WORD_FF))) | LL_TIMER_CON_DIVISION_SET(p_init->prescaler);
    tmr_con = (tmr_con & (~LL_TIMER_CON_SRC_SEL(ALL_WORD_FF))) | LL_TIMER_CON_SRC_SEL(p_init->timer_src_sel);
    tmr_con |= LL_TIMER_CON_CNT_PENDING | LL_TIMER_CON_CAP_PENDING;
    p_timer->TMR_CON = tmr_con;
}

/**
  * @brief  Low layer timer disable function
  * @param  p_timer  : Structure pointer set to TIMER5
  * @retval None
  */
void ll_irtimer_stop(TIMER5_TypeDef *p_timer)
{
    u32 cnt_con = p_timer->TMR_CON;
    cnt_con = (cnt_con & (~LL_TIMER_CON_MODE_SET(ALL_WORD_FF))) | LL_TIMER_CON_MODE_SET(LL_TIMER_MODE_SEL_DISABLE);
    cnt_con |= LL_TIMER_CON_CNT_PENDING | LL_TIMER_CON_CAP_PENDING;
    p_timer->TMR_CON = cnt_con;
}

/**
  * @brief  Low layer timer start function
  * @param  p_timer  : Structure pointer set to TIMER5
  * @retval None
  */
void ll_irtimer_start(TIMER5_TypeDef *p_timer, TYPE_ENUM_LL_TIMER_MODE_SEL mode_sel)
{
    u32 cnt_con = p_timer->TMR_CON;
    cnt_con = (cnt_con & (~LL_TIMER_CON_MODE_SET(ALL_WORD_FF))) | LL_TIMER_CON_MODE_SET(mode_sel);
    cnt_con |= LL_TIMER_CON_CNT_PENDING | LL_TIMER_CON_CAP_PENDING;
    p_timer->TMR_CON = cnt_con;
}

/**
  * @brief  Low layer timer5 cnt set
  * @param  p_timer  : Structure pointer set to TIMERx
  * @param  cnt_set  : timer5 cnt value(timer5 16bits cnt value)
  * @retval None
  */
void ll_irtimer_cnt_set(TIMER5_TypeDef *p_timer, u32 cnt_set)
{
    p_timer->TMR_CNT = (u16)cnt_set;
}

/**
  * @brief  Low layer timer5 cnt get
  * @param  p_timer  : Structure pointer set to TIMERx
  * @retval timer5 cnt value(timer5 16bits cnt value)
  */
u32 ll_irtimer_cnt_get(TIMER5_TypeDef *p_timer)
{

    return (p_timer->TMR_CNT);

}

/**
  * @brief  set timer to count mode
  * @param  p_timer  : Structure pointer set to TIMER5
  * @param  cnt_cfg  : Structure pointer set to TIMERx counter mode
  * @retval None
  */
void ll_irtimer_cnt_mode_config(TIMER5_TypeDef *p_timer, TYPE_LL_TIMER_CNT_CFG *cnt_cfg)
{
    u32 cnt_con = 0;
    
    p_timer->TMR_CNT  = cnt_cfg->count_initial;
    p_timer->TMR_PR   = cnt_cfg->count_period;
    
    cnt_con = p_timer->TMR_CON;
    /* cnt_con = (cnt_con & (~LL_TIMER_CON_MODE_SET(ALL_WORD_FF))) | LL_TIMER_CON_MODE_SET(LL_TIMER_MODE_SEL_COUNTER); */
    if(cnt_cfg->count_ie)
    {
        cnt_con |= LL_TIMER_CON_CNT_IE;
    }
    else
    {
        cnt_con &= ~LL_TIMER_CON_CNT_IE;
    }
    cnt_con &= ~(LL_TIMER_CON_CNT_PENDING | LL_TIMER_CON_CAP_PENDING);
    p_timer->TMR_CON |= cnt_con; 
}

/**
  * @brief  Set timer to pwm mode
  * @param  p_timer  : Structure pointer set to TIMER5
  * @param  pwm_cfg  : Structure pointer set to TIMERx pwm mode
  * @retval None
  */
void ll_irtimer_pwm_mode_config(TIMER5_TypeDef *p_timer, TYPE_LL_TIMER_PWM_CFG *pwm_cfg)
{    
    u32 pwm_con = 0;
    p_timer->TMR_CNT  = 0;
    p_timer->TMR_PR   = pwm_cfg->pwm_period;
    p_timer->TMR_PWM  = pwm_cfg->pwm_duty;
    pwm_con = p_timer->TMR_CON;
    /* pwm_con = (pwm_con & (~LL_TIMER_CON_CAP_EDGE_SET(ALL_WORD_FF))) | LL_TIMER_CON_CAP_EDGE_SET(LL_TIMER_MODE_SEL_PWM); */
    pwm_con &= ~(LL_TIMER_CON_CNT_PENDING | LL_TIMER_CON_CAP_PENDING);
    p_timer->TMR_CON |= LL_TIMER_CON_MODE_SET(LL_TIMER_MODE_SEL_PWM);
}

/**
  * @brief  Set timer to capture mode 
  * @param  p_timer  : Structure pointer set to TIMER5
  * @param  cap_cfg  : Structure pointer set to TIMERx capture mode
  * @retval None
  */
void ll_irtimer_cap_mode_config(TIMER5_TypeDef *p_timer, TYPE_LL_TIMER_CAP_CFG *cap_cfg)
{
    u32 cap_con = 0;
    p_timer->TMR_CNT  = 0;
    p_timer->TMR_PR   = 0xFFFFFFFF;
    cap_con = p_timer->TMR_CON;
    cap_con = (cap_con & (~LL_TIMER_CON_CAP_EDGE_SET(ALL_WORD_FF))) | LL_TIMER_CON_CAP_EDGE_SET(cap_cfg->capture_edge_sel);
    /* cap_con = (cap_con & (~LL_TIMER_CON_MODE_SET(ALL_WORD_FF))) | LL_TIMER_CON_MODE_SET(LL_TIMER_MODE_SEL_CAPTURE); */
    if(cap_cfg->capture_ie)
    {
        cap_con |= LL_TIMER_CON_CAP_IE;
    }
    else
    {
        cap_con &= ~LL_TIMER_CON_CAP_IE;
    }
    cap_con &= ~(LL_TIMER_CON_CNT_PENDING | LL_TIMER_CON_CAP_PENDING);
    p_timer->TMR_CON = cap_con;
}


/**
  * @brief  Infrared send initialization
  * @param  p_timer       : Structure pointer set to TIMER5
  * @param  ir_tx_cfg     : Structure pointer set to TIMER5 infrared send configure
  * @retval None
  */
/* when time5 is used to the infrared sending, TIMER0 is need */
void ll_ir_tx_init(TIMER5_TypeDef *p_timer, TYPE_LL_IR_TX_CFG *ir_tx_cfg)
{
    TYPE_LL_TIMER_INIT timer_init;
    TYPE_LL_TIMER_PWM_CFG pwm_cfg = {0};

    /* xoren is used to which contrling RC5 to send ( 0:CW + Signal or 1:signal + CW )  */
    /* polsel is used to which contrling PWM polarity */
    p_timer->TMR_IRSTA = (ir_tx_cfg->xor_en ? LL_IRTIMER_IRSTA_XOREN : 0) | (ir_tx_cfg->p_pol_en ? LL_IRTIMER_IRSTA_POLSEL : 0);
    /* set timer0 to PWM model, output carrier signal */
    timer_init.prescaler = LL_TIMER_PSC_NONE;
    timer_init.timer_src_sel = LL_TIMER_SRC_SYS_RISING;
    ll_timer_init(TIMER0, &timer_init);

    pwm_cfg.pwm_duty = SYS_CLK/ir_tx_cfg->carrier_freq/2-1;
    pwm_cfg.pwm_period = SYS_CLK/ir_tx_cfg->carrier_freq-1;
    ll_timer_pwm_mode_config(TIMER0, &pwm_cfg);
    /* Set the cycle time and carrier duration of infrared transmission 1 */
    p_timer->TMR_PR0  = LL_IRTIMER_PR0(ir_tx_cfg->bit_1_period_cnt);
    p_timer->TMR_PWM0 = LL_IRTIMER_PWM0(ir_tx_cfg->bit_1_carrier_cnt);

    /* Set the cycle time and carrier duration of infrared transmission 0 */
    p_timer->TMR_PR1  = LL_IRTIMER_PR1(ir_tx_cfg->bit_0_period_cnt);
    p_timer->TMR_PWM1 = LL_IRTIMER_PWM1(ir_tx_cfg->bit_0_carrier_cnt);
}



/**
  * @brief  Send infrared data
  * @param  p_timer     : Structure pointer set to TIMER5
  * @param  p_ir_frame  : Structure pointer set to Infrared structure
  * @retval None
  */
void ll_ir_tx(TIMER5_TypeDef *p_timer, TYPE_LL_IR_FRAME_CFG *p_ir_frame)
{
    u16 *buf = p_ir_frame->ir_buf;
    p_timer->TMR_CON &= ~LL_TIMER_CON_MODE_SET(ALL_WORD_FF);
    p_timer->TMR_CNT     = 0x0000;
    TIMER0->TMR_CON &= ~LL_TIMER_CON_MODE_SET(ALL_WORD_FF);
    TIMER0->TMR_CNT     = 0x0000;
    
    /* The start bit is reconfigured while sending each time */
    p_timer->TMR_PR      = p_ir_frame->start_bit_period_cnt;
    p_timer->TMR_PWM     = p_ir_frame->start_bit_carrier_cnt;
    p_timer->TMR_BITCNT  = p_ir_frame->frame_bit_cnt;
    
    p_timer->TMR_IRSTA  |= LL_IRTIMER_IRSTA_TX_DONE_PENDING | LL_IRTIMER_IRSTA_BUF_FULL_ERR_PENDING |
                           LL_IRTIMER_IRSTA_BUF_EMPTY_ERR_PENDING | LL_IRTIMER_IRSTA_IR_EN;
    
    p_timer->TMR_CON     |= LL_TIMER_CON_MODE_SET(LL_TIMER_MODE_SEL_PWM);
    /* open the PWM mode of TIMER0 */
    /* closeding TIMER0 and clearing value of CNT to void unwanted impulses */
    TIMER0->TMR_CON |= LL_TIMER_CON_MODE_SET(LL_TIMER_MODE_SEL_PWM);
    
    while(!(p_timer->TMR_IRSTA & LL_IRTIMER_IRSTA_TX_DONE_PENDING))
    {
        __asm("nop");
        if((p_timer->TMR_IRSTA & LL_IRTIMER_IRSTA_WDATA_REQ))
        {
            p_timer->TMR_TXDAT = *buf++;
        }
        __asm("nop");
    }
}

/**
  * @brief  Send infrared data( using interrupt mode )
  * @param  p_timer     : Structure pointer set to TIMER5
  * @param  p_ir_frame  : Structure pointer set to Infrared structure
  * @retval None
  */
void ll_ir_int_tx(TIMER5_TypeDef *p_timer, TYPE_LL_IR_FRAME_CFG *p_ir_frame)
{
    p_timer->TMR_CON &= ~LL_TIMER_CON_MODE_SET(ALL_WORD_FF);
    p_timer->TMR_CNT     = 0x0000;
    TIMER0->TMR_CON &= ~LL_TIMER_CON_MODE_SET(ALL_WORD_FF);
    TIMER0->TMR_CNT     = 0x0000;
    
    p_timer->TMR_IRSTA  |= LL_IRTIMER_IRSTA_TX_DONE_PENDING | LL_IRTIMER_IRSTA_BUF_FULL_ERR_PENDING |
                           LL_IRTIMER_IRSTA_BUF_EMPTY_ERR_PENDING | LL_IRTIMER_IRSTA_BUF_EMPTY_IE |
                           LL_IRTIMER_IRSTA_TX_DONE_IE | LL_IRTIMER_IRSTA_IR_EN;

    /* The start bit is reconfigured while sending each time */
    p_timer->TMR_PR      = LL_IRTIMER_PR(p_ir_frame->start_bit_period_cnt);
    p_timer->TMR_PWM     = LL_IRTIMER_PWM(p_ir_frame->start_bit_carrier_cnt);
    p_timer->TMR_BITCNT  = p_ir_frame->frame_bit_cnt;
    /* p_timer->TMR_CON    |= LL_TIMER_CON_MODE_SET(LL_TIMER_MODE_SEL_PWM); */
    p_timer->TMR_CON = ((p_timer->TMR_CON) & (~LL_TIMER_CON_MODE_SET(ALL_WORD_FF))) | LL_TIMER_CON_MODE_SET(LL_TIMER_MODE_SEL_PWM);
    /* open the PWM mode of TIMER0 */
    /* closeding TIMER0 and clearing value of CNT to void unwanted impulses */
    /* TIMER0->TMR_CON |= LL_TIMER_CON_MODE_SET(LL_TIMER_MODE_SEL_PWM); */
    TIMER0->TMR_CON = ((TIMER0->TMR_CON) & (~LL_TIMER_CON_MODE_SET(ALL_WORD_FF))) | LL_TIMER_CON_MODE_SET(LL_TIMER_MODE_SEL_PWM);
}

/**
  * @brief  Low layer timer counter interrupt enable function
  * @param  p_timer  : Structure pointer set to TIMER0 ~ TIMER5
  * @retval None
  */
void ll_timer_cnt_interrupt_enable(TIMER_TypeDef *p_timer)
{
    p_timer->TMR_CON = (p_timer->TMR_CON & (~LL_TIMER_CON_CNT_AND_CAP_PENDING_MASK)) | LL_TIMER_CON_CNT_IE;
}
/**
  * @brief  Low layer timer counter interrupt disable function
  * @param  p_timer  : Structure pointer set to TIMER0 ~ TIMER5
  * @retval None
  */
void ll_timer_cnt_interrrupt_disable(TIMER_TypeDef *p_timer)
{
    p_timer->TMR_CON = p_timer->TMR_CON & (~LL_TIMER_CON_CNT_AND_CAP_PENDING_MASK) & (~LL_TIMER_CON_CNT_IE);
}

/**
  * @brief  Low layer timer capture interrupt enable function
  * @param  p_timer  : Structure pointer set to TIMER0 ~ TIMER5
  * @retval None
  */
void ll_timer_cap_interrupt_enable(TIMER_TypeDef *p_timer)
{
    p_timer->TMR_CON = (p_timer->TMR_CON & (~LL_TIMER_CON_CNT_AND_CAP_PENDING_MASK)) | LL_TIMER_CON_CAP_IE;
}

/**
  * @brief  Low layer timer capture interrupt disable function
  * @param  p_timer  : Structure pointer set to TIMER0 ~ TIMER5
  * @retval None
  */
void ll_timer_cap_interrupt_disable(TIMER_TypeDef *p_timer)
{
    p_timer->TMR_CON = p_timer->TMR_CON & (~LL_TIMER_CON_CNT_AND_CAP_PENDING_MASK) & (~LL_TIMER_CON_CAP_IE);
}

/**
  * @brief  Low layer Infrared transmission data buf empty interrupt enable function
  * @param  p_timer  : Structure pointer set to TIMER5
  * @retval None
  */
void ll_irtimer_buf_empty_interrupt_enable(TIMER5_TypeDef *p_timer)
{
    p_timer->TMR_IRSTA = (p_timer->TMR_IRSTA & (~LL_IRTIMER_IRSTA_ALL_PENDING_MASK)) | LL_IRTIMER_IRSTA_BUF_EMPTY_IE;
}

/**
  * @brief  Low layer Infrared transmission data buf empty interrupt disable function
  * @param  p_timer  : Structure pointer set to TIMER5
  * @retval None
  */
void ll_irtimer_buf_empty_interrupt_disable(TIMER5_TypeDef *p_timer)
{
    p_timer->TMR_IRSTA = p_timer->TMR_IRSTA & (~LL_IRTIMER_IRSTA_ALL_PENDING_MASK) & (~LL_IRTIMER_IRSTA_BUF_EMPTY_IE);
}

/**
  * @brief  Low layer infrared transmission done interrupt enable function
  * @param  p_timer  : Structure pointer set to TIMER5
  * @retval None
  */
void ll_irtimer_tx_done_interrupt_enable(TIMER5_TypeDef *p_timer)
{
    p_timer->TMR_IRSTA = ((p_timer)->TMR_IRSTA & (~LL_IRTIMER_IRSTA_ALL_PENDING_MASK)) | LL_IRTIMER_IRSTA_TX_DONE_IE;
}

/**
  * @brief  Low layer infrared transmission done interrupt disable function
  * @param  p_timer  : Structure pointer set to TIMER5
  * @retval None
  */
void ll_irtimer_tx_done_interrupt_disable(TIMER5_TypeDef *p_timer)
{
    p_timer->TMR_IRSTA = p_timer->TMR_IRSTA & (~LL_IRTIMER_IRSTA_ALL_PENDING_MASK) & (~LL_IRTIMER_IRSTA_TX_DONE_IE);
}

/**
  * @brief  Low layer infrared enabled function
  * @param  p_timer  : Structure pointer set to TIMER5
  * @retval None
  */
void ll_irtimer_ir_enable(TIMER5_TypeDef *p_timer)
{
    p_timer->TMR_IRSTA = (p_timer->TMR_IRSTA & (~LL_IRTIMER_IRSTA_ALL_PENDING_MASK)) | LL_IRTIMER_IRSTA_IR_EN;
}

/**
  * @brief  Low layer infrared disable function
  * @param  p_timer  : Structure pointer set to TIMER5
  * @retval None
  */
void ll_irtimer_ir_disable(TIMER5_TypeDef *p_timer)
{
    p_timer->TMR_IRSTA = p_timer->TMR_IRSTA & (~LL_IRTIMER_IRSTA_ALL_PENDING_MASK) & (~LL_IRTIMER_IRSTA_IR_EN);
}

/**
  * @brief  calculate timer timeout to count period (Timer1-Timer3  advice 1ms(when use system pll && timer clock is system clock )
  * @param  p_timer  :      Structure pointer set to TIMERx
  * @param  src_sel  :      Timer clock source selection
  * @param  psc             Structure pointer set to TIMERx counter mode
  * @param  source_ms_data  
  * @note   This function can only be used for timers using the system clock (internal clock and PLL).    
  *         Timer0-Timer3  advice 1ms(psc = LL_TIMER_PSC_4),   2-10ms(psc=LL_TIMER_PSC_16),  11-30ms(psc=LL_TIMER_PSC_32), 30-70ms(psc=LL_TIMER_PSC_64)   71-100ms(psc=LL_TIMER_PSC_128)    
  *         Timer4         advice 1ms-1s(psc = LL_TIMER_PSC_4)   
  *         advise to use psc=LL_TIMER_PSC_4   
  * @retval None  
  */
u32 ll_timer_ms_cal(TIMER_TypeDef *p_timer,TYPE_ENUM_LL_TIMER_SRC_SEL src_sel, TYPE_ENUM_LL_TIMER_PSC psc, u16 delay_ms_data)
{
    u8 psc_list[8] = {1, 2, 4, 8, 16, 32, 64, 128};
    u32 target_ms_value = 0;
    u32 *p = (u32 *)0x1FF00630;
    u32 rc_reg_value = ((*p) >> 7 ) & 0x7FFF;
    if(((SYSCTRL->CLK_CON0 & 0x3) == 0x3) && (((SYSCTRL->CLK_CON0>>4)&0x3) == 0x2) && (LL_TIMER_SRC_SYS_RISING == src_sel))   //select system pll && select 26M_RC
    {
        target_ms_value = (rc_reg_value * 2 * delay_ms_data /psc_list[psc]) -1 ;
        if(TIMER4 != p_timer)
        {
            return (target_ms_value >= 65535 ? 0:target_ms_value);
        }
        else
        {
            return target_ms_value;
        }
    }
    return 0;
}


/**
  * @brief  timer count initialization (Timer0-Timer3  advice timing time <1ms; Timer4 advice timing timer <10s
  * @param  p_timer  :      Structure pointer set to TIMERx
  * @param  timing_ms:      Timer timing ms
  * @param  irq_sta  :      Count Interrupt enable or disable
  * @note   This function help user to initial timing time.      
  * @retval None  
  */
void ll_timer_count_init(TIMER_TypeDef *p_timer, u32 timing_ms, FunctionalState irq_sta)
{
    TYPE_LL_TIMER_INIT timer_cfg;
    TYPE_LL_TIMER_CNT_CFG cnt_cfg;    
    u8 psc_list[8] = {1, 2, 4, 8, 16, 32, 64, 128};
    u32 *p = (u32 *)0x1FF00630;
    u32 rc_reg_value = ((*p) >> 7 ) & 0x7FFF;
    u32 sys_value_khz = 0;
    
    memset(&timer_cfg, 0x00, sizeof(timer_cfg));
    memset(&cnt_cfg, 0x00, sizeof(cnt_cfg));
    
    if((rc_reg_value<25000) || (rc_reg_value>27000))
    {
        return;
    }
    if(TIMER4 != p_timer)
    {
        if(((SYSCTRL->CLK_CON0 & 0x3) == 0x3) && (((SYSCTRL->CLK_CON0>>4)&0x1) == 0x0)){   //sys_clk select pll && pll_select 26M_RC
            if((rc_reg_value<25000)||(rc_reg_value>27000)){
                sys_value_khz = 2 * rc_reg_value;
            }
            else{
                sys_value_khz = 52000;
            }
        }
        else if((SYSCTRL->CLK_CON0 & 0x3) == 0x2){       //sys_clk select hirc=26MHz
            if((rc_reg_value<25000)||(rc_reg_value>27000)){
                sys_value_khz = rc_reg_value;
            }
            else{
                sys_value_khz = 26000;
            }
        }
        else{
            return;
        }
        if(timing_ms == 0){
            return;
        }
        if(timing_ms == 1){
            timer_cfg.timer_src_sel = LL_TIMER_SRC_SYS_RISING;
            timer_cfg.prescaler = LL_TIMER_PSC_NONE;
        }
        else if(timing_ms == 2){
            timer_cfg.timer_src_sel = LL_TIMER_SRC_SYS_RISING;
            timer_cfg.prescaler = LL_TIMER_PSC_2; 
        }
        else if(timing_ms <= 4){
            timer_cfg.timer_src_sel = LL_TIMER_SRC_SYS_RISING;
            timer_cfg.prescaler = LL_TIMER_PSC_4; 
        }
        else if(timing_ms <= 8){
            timer_cfg.timer_src_sel = LL_TIMER_SRC_SYS_RISING;
            timer_cfg.prescaler = LL_TIMER_PSC_8; 
        }
        else if(timing_ms <= 16){
            timer_cfg.timer_src_sel = LL_TIMER_SRC_SYS_RISING;
            timer_cfg.prescaler = LL_TIMER_PSC_16;
        }
        else if(timing_ms <= 32){
            timer_cfg.timer_src_sel = LL_TIMER_SRC_SYS_RISING;
            timer_cfg.prescaler = LL_TIMER_PSC_32;        
        }
        else if(timing_ms <= 64){
            timer_cfg.timer_src_sel = LL_TIMER_SRC_SYS_RISING;
            timer_cfg.prescaler = LL_TIMER_PSC_64;        
        }
        else if(timing_ms <= 100){
            timer_cfg.timer_src_sel = LL_TIMER_SRC_SYS_RISING;
            timer_cfg.prescaler = LL_TIMER_PSC_128;        
        }
        else{
            return;
        }
    }
    else{
        if(timing_ms<=10000){
            timer_cfg.timer_src_sel = LL_TIMER_SRC_SYS_RISING;
            timer_cfg.prescaler = LL_TIMER_PSC_NONE;
        }
        else{
            return;
        }
    }
    ll_timer_init(p_timer, &timer_cfg);
    
    cnt_cfg.count_initial = 0;
    cnt_cfg.count_period = (sys_value_khz * timing_ms /psc_list[timer_cfg.prescaler]) -1 ;
    cnt_cfg.count_ie = irq_sta;
    ll_timer_cnt_mode_config(p_timer, &cnt_cfg);
}
/**
  * @brief  calculate timer pwm
  * @param  p_timer  :      Structure pointer set to TIMERx
  * @param  freq_hz  :      freq(hz) value from 10Hz----1MHz 
  * @param  duty_per :      duty percentage from 1---100
  * @note   duty_time==timer_count * prescaler / timer_src_sel
  *         freq   = timer_src_sel /(timer_count * prescaler)
  *         timer_count = (timer_src_sel /freq )/prescaler
  * @retval None  
  */
void ll_timer_pwm_init(TIMER_TypeDef *p_timer, u32 freq_hz, u8 duty_per)
{
    #define SYSTEM_CLK   SYS_CLK       //52000000      //system_clock=52MHz
    #define FREQ_MIN     10            //10Hz
    #define FREQ_MID     500000        //500kHz
    #define FREQ_MAX     1000000       //1MHz
    TYPE_LL_TIMER_INIT timer_cfg;
    TYPE_LL_TIMER_PWM_CFG pwm_cfg;
    u8 psc_list[8] = {1, 2, 4, 8, 16, 32, 64, 128};
    u8 psc_index=0;
    u32 temp = SYSTEM_CLK / freq_hz;
    
    memset(&timer_cfg, 0x00, sizeof(timer_cfg));
    memset(&pwm_cfg, 0x00, sizeof(pwm_cfg));
    
    if(duty_per >99)
    {
        /* timer initialization */
        timer_cfg.prescaler = LL_TIMER_PSC_NONE;
        timer_cfg.timer_src_sel = LL_TIMER_SRC_SYS_RISING;
        ll_timer_init(p_timer, &timer_cfg);
        /* PWM output */
        pwm_cfg.pwm_duty = 1;
        pwm_cfg.pwm_period = 0;
        ll_timer_pwm_mode_config(p_timer, &pwm_cfg);
    }
    else if(duty_per <1)
    {
        /* timer initialization */
        timer_cfg.prescaler = LL_TIMER_PSC_128;
        timer_cfg.timer_src_sel = LL_TIMER_SRC_SYS_RISING;
        ll_timer_init(p_timer, &timer_cfg);
        /* PWM output */
        pwm_cfg.pwm_duty = 10000;
        pwm_cfg.pwm_period = 10000;
        ll_timer_pwm_mode_config(p_timer, &pwm_cfg);
        
    }
    else
    {
        if(freq_hz>=FREQ_MIN && freq_hz<=FREQ_MID)
        {
            for(psc_index=0;psc_index<8;psc_index++)
            {
                if(temp/psc_list[psc_index] < 65535)
                {
                    break;
                }
            }
            /* timer initialization */
            timer_cfg.prescaler = (TYPE_ENUM_LL_TIMER_PSC)psc_index;
            timer_cfg.timer_src_sel = LL_TIMER_SRC_SYS_RISING;
            ll_timer_init(p_timer, &timer_cfg);
            /* PWM output */
            pwm_cfg.pwm_duty = (temp * duty_per)/(psc_list[psc_index]*100);
            pwm_cfg.pwm_period = temp/psc_list[psc_index];
            ll_timer_pwm_mode_config(p_timer, &pwm_cfg);
        }
        else if(freq_hz>FREQ_MID && freq_hz<=FREQ_MAX)
        {
            /* timer initialization */
            timer_cfg.prescaler = LL_TIMER_PSC_NONE;
            timer_cfg.timer_src_sel = LL_TIMER_SRC_SYS_RISING;
            ll_timer_init(p_timer, &timer_cfg);
            /* PWM output */
            pwm_cfg.pwm_duty = (temp * duty_per)/100;
            pwm_cfg.pwm_period = temp;
            ll_timer_pwm_mode_config(p_timer, &pwm_cfg);
        }
    }
}


/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/*************************** (C) COPYRIGHT 2018 TOPSYS ***** END OF FILE *****/
